#include <iostream>
#include <string>
#include <stack>
#include <vector>
#include <bitset>
#include <complex>
#include <hashtable.h>

using namespace std;

// template<typename... Values> class tuple;

// template<> class tuple<> {};

// template<typename Head, typename... Tail>
// class tuple<Head, Tail...> : private tuple<Tail...> {
//     typedef tuple<Tail...> inherited;
// public:
//     tuple() {}
//     tuple(Head v, Tail... vtail) : m_head(v), inherited(vtail...) {}
//     typename Head::type head() { return m_head; }
//     inherited& tail() { return *this; }

// protected:
//     Head m_head;
// };




template <typename T>
class AutoPtr {
public:
    explicit AutoPtr(T* ptr = nullptr) : _ptr(ptr) { cout << "set new obj: " << _ptr << endl; }

    T* operator->() { return this->_ptr; }

    T& operator*() { return *(operator->()); }

    ~AutoPtr() {
        cout << "delete obj: " << _ptr << endl;
        if (!_ptr) delete _ptr;
    }

private:
    T* _ptr;
};

class MyClass{
public:
    MyClass() { cout << "construct MyClass func" << endl; }

    void print() { cout << "hello" << endl; }

    ~MyClass(){ cout << "deconstruct MyClass func" << endl; }
};

int main(int argc, char const *argv[]) {

    AutoPtr<MyClass> myclass(new MyClass());

    myclass->print();
    (*myclass).print();

    AutoPtr<MyClass> newPtr = myclass;
    
    return 0;
}
